package com.astruyk.battlegroundAndroid.data;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
import com.astruyk.battlegroundAndroid.data.CapturePoint;

/**
 * Content provider for Battleground Europe data as parsed from the website. The data
 * exposed by this content provider is a mixture of pre-cached data and live data.
 * 
 * @author Anton Struyk
 */
public class BattlegroundAndroidProvider extends ContentProvider {
	public static final String AUTHORITY = "com.astruyk.battlegroundandroid.data";
	public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY);

    private static final String DATABASE_NAME = "battlegroundEurope.db";
	private static final int DATABASE_VERSION = 1;
	
	private static final String CP_TABLE_NAME = "Towns";
	private static final String COUNTRY_TABLE_NAME = "Countries";
	private static final String SIDE_TABLE_NAME = "Sides";
	private static final String CP_TYPES_TABLE_NAME = "CpTypes";
	private static final String FACILITY_TYPES_TABLE_NAME = "FacilityTypes";

	/**
	 * Matcher that is used to determine what UriId was passed to a content URI request
	 */
	private static final UriMatcher _uriMatcher;
	static{
		_uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
		_uriMatcher.addURI(AUTHORITY, "towns", UriId.TOWN);
		_uriMatcher.addURI(AUTHORITY, "towns/#", UriId.TOWN_ID);		
	}
	
	/**
	 * Helper class that manages the database
	 */
	private static class DatabaseHelper extends SQLiteOpenHelper{
		public DatabaseHelper(Context context) {
			super(context, DATABASE_NAME, null, DATABASE_VERSION);
		}
	 	@Override
		public void onCreate(SQLiteDatabase db) {
			db.execSQL("CREATE TABLE " + CP_TABLE_NAME + " (" 
					+ CapturePoint._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
					+ CapturePoint.NAME + " TEXT, "
					+ CapturePoint.TYPE + " INTEGER, "
					+ CapturePoint.ORIG_COUNTRY + " INTEGER, "
					+ CapturePoint.ORIG_SIDE + " INTEGER, "
					+ CapturePoint.LINKS + " INTEGER, "
					+ CapturePoint.X + " INTEGER, "
					+ CapturePoint.Y + " INTEGER, "
					+ CapturePoint.ABS_X + " INTEGER, "
					+ CapturePoint.ABS_Y + " INTEGER, "
					+ CapturePoint.SCALED_X + " REAL, "
					+ CapturePoint.SCALED_Y + " REAL"
					+ ");");
		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			Log.w("MyDBHelper", "Upgrading from version " +
					oldVersion + " to " + newVersion +
					" which will destroy all old data");
			db.execSQL("DROP TABLE IF EXISTS " + CP_TABLE_NAME);
			onCreate(db);
		}
	}
	
	private DatabaseHelper _openHelper;
	
	@Override
	public boolean onCreate(){
		_openHelper = new DatabaseHelper(getContext());
		return true;
	}
	
	@Override
	public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder){
		SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
		
		String orderBy;
		switch(_uriMatcher.match(uri)){
		case (UriId.TOWN):
			qb.setTables(CP_TABLE_NAME);
			orderBy = CapturePoint.NAME + " DESC";
			break;
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}
		
		//If the user specified a sort order, override the default
		if(!TextUtils.isEmpty(sortOrder)){
			orderBy = sortOrder;
		}
		
		//Get the database and run the query
		SQLiteDatabase db = _openHelper.getReadableDatabase();
		Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy);
		
		//Tell the cursor what URI to watch, so it knows when the source data changes
		c.setNotificationUri(getContext().getContentResolver(), uri);
		return c;
	}
	
	@Override
	public String getType(Uri uri){
		switch(_uriMatcher.match(uri)){
		case UriId.TOWN:
			return "vnd.android.cursor.dir/vnd.battleground.cp";
		case UriId.TOWN_ID:
			return "vnd.android.cursor.item/vnd.battleground.cp";
			
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}
	}
	
	@Override
	public Uri insert(Uri uri, ContentValues initialValues){
		//Validate the requested URI
		if(_uriMatcher.match(uri) != UriId.TOWN){
			throw new IllegalArgumentException("Unknown URI " + uri);
			//TODO make sure that the other types of insert are supported
		}
		
		ContentValues values;
		if(initialValues != null){
			values = new ContentValues(initialValues);
		}else{
			values = new ContentValues();
		}

		//TODO ensure the other fields are also present...
		if(!values.containsKey(CapturePoint.NAME)){
			values.put(CapturePoint.NAME, "Unknown");
		}
		
		SQLiteDatabase db = _openHelper.getWritableDatabase();
		long rowId = db.insert(CP_TABLE_NAME, CapturePoint.NAME, values);
		if(rowId > 0){
			Uri townUri = ContentUris.withAppendedId(CapturePoint.CONTENT_URI, rowId);
			getContext().getContentResolver().notifyChange(townUri, null);
			return townUri;
		}
		
		throw new SQLException("Failed to insert row into " + uri);
	}
	
	@Override
	public int delete(Uri uri, String where, String[] whereArgs){
		SQLiteDatabase db = _openHelper.getWritableDatabase();
		
		int count;
		switch(_uriMatcher.match(uri)){
		case UriId.TOWN:
			count = db.delete(CP_TABLE_NAME, where, whereArgs);
			break;
		case UriId.TOWN_ID:
			String townId = uri.getPathSegments().get(1);
			count = db.delete(
					CP_TABLE_NAME,
					CapturePoint._ID + "=" + townId + (!TextUtils.isEmpty(where) ? " AND (" + where + ")" : ""),
					whereArgs);
			break;
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}
		
		getContext().getContentResolver().notifyChange(uri, null);
		return count;
	}
	
	@Override
	public int update(Uri uri, ContentValues values, String where, String[] whereArgs){
		SQLiteDatabase db = _openHelper.getWritableDatabase();
		int count;
		switch(_uriMatcher.match(uri)){
		case UriId.TOWN:
			count = db.update(CP_TABLE_NAME, values, where, whereArgs);
			break;
			
		case UriId.TOWN_ID:
			String townId = uri.getPathSegments().get(1);
			count = db.update(
					CP_TABLE_NAME,
					values,
					CapturePoint._ID + "=" + townId + (!TextUtils.isEmpty(where) ? " AND (" + where + ")" : ""),
					whereArgs);
			break;
		
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}
		
		getContext().getContentResolver().notifyChange(uri, null);
		return count;
	}
	
	private static class UriId{
		private UriId(){}
		
		public static final int TOWN = 1;
		public static final int TOWN_ID = 2;
	}
}
